using JGSY.CMS.LowCode.Platform.Infrastructure.Middleware;
using JGSY.CMS.LowCode.Platform.Infrastructure.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Extensions
{
    /// <summary>
    /// 中间件配置扩展
    /// </summary>
    public static class MiddlewareExtensions
    {
        /// <summary>
        /// 添加自定义中间件服务
        /// </summary>
        public static IServiceCollection AddCustomMiddleware(this IServiceCollection services, IConfiguration configuration)
        {
            // 添加速率限制选项
            services.Configure<RateLimitOptions>(configuration.GetSection("RateLimit"));
            
            // 添加安全头选项
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            if (environment == "Development")
            {
                services.AddSingleton(SecurityHeadersOptions.Development());
            }
            else
            {
                var allowedOrigins = configuration.GetSection("Cors:AllowedOrigins").Get<List<string>>() ?? new List<string>();
                services.AddSingleton(SecurityHeadersOptions.Production(allowedOrigins));
            }

            return services;
        }

        /// <summary>
        /// 使用自定义中间件管道
        /// </summary>
        public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder app, IConfiguration configuration)
        {
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

            // 创建配置映射工厂来获取强类型配置
            var configFactory = new EnhancedConfigurationMappingFactory(configuration);
            var rateLimitConfig = configFactory.GetRateLimitConfiguration();
            var corsConfig = configFactory.GetCorsConfiguration();
            var permissionConfig = configFactory.GetPermissionConfiguration();

            // 1. 安全头中间件（最先执行）
            app.UseMiddleware<SecurityHeadersMiddleware>();

            // 2. 异常处理中间件
            app.UseMiddleware<ExceptionHandlingMiddleware>();

            // 3. 请求响应日志记录中间件 - 从独立配置节获取
            var requestResponseLoggingEnabled = configuration.GetSection("RequestResponseLogging:Enabled").Get<bool?>() ?? true;
            if (requestResponseLoggingEnabled)
            {
                app.UseMiddleware<RequestResponseLoggingMiddleware>();
            }

            // 4. 速率限制中间件
            if (rateLimitConfig.Enabled)
            {
                app.UseMiddleware<RateLimitingMiddleware>();
            }

            // 5. HTTPS 重定向（生产环境）
            if (environment != "Development")
            {
                app.UseHttpsRedirection();
            }

            // 6. 静态文件服务
            app.UseStaticFiles();

            // 7. 路由
            app.UseRouting();

            // 8. CORS（如果启用）
            if (corsConfig.Enabled)
            {
                app.UseCors("DefaultCorsPolicy");
            }

            // 9. JWT中间件（在认证之前）
            app.UseJwtMiddleware();

            // 10. 认证
            app.UseAuthentication();

            // 11. 权限验证中间件（在认证之后）
            if (permissionConfig.Enabled)
            {
                app.UseMiddleware<PermissionMiddleware>();
            }

            // 12. 授权
            app.UseAuthorization();

            return app;
        }

        /// <summary>
        /// 配置CORS策略
        /// </summary>
        public static IServiceCollection AddCustomCors(this IServiceCollection services, IConfiguration configuration)
        {
            // 获取增强配置
            var configFactory = new EnhancedConfigurationMappingFactory(configuration);
            var corsConfig = configFactory.GetCorsConfiguration();
            
            services.AddCors(options =>
            {
                options.AddPolicy("DefaultCorsPolicy", builder =>
                {
                    var allowedOrigins = corsConfig.GetAllOrigins();
                    var allowedMethods = corsConfig.AllowedMethods;
                    var allowedHeaders = corsConfig.AllowedHeaders;

                    if (allowedOrigins.Contains("*"))
                    {
                        builder.AllowAnyOrigin();
                    }
                    else
                    {
                        builder.WithOrigins(allowedOrigins.ToArray());
                    }

                    builder.WithMethods(allowedMethods.ToArray())
                           .WithHeaders(allowedHeaders.ToArray());

                    if (corsConfig.AllowCredentials && !allowedOrigins.Contains("*"))
                    {
                        builder.AllowCredentials();
                    }
                });

                // API专用CORS策略
                options.AddPolicy("ApiCorsPolicy", builder =>
                {
                    builder.WithOrigins(configuration.GetSection("Cors:ApiAllowedOrigins").Get<string[]>() ?? Array.Empty<string>())
                           .AllowAnyMethod()
                           .AllowAnyHeader()
                           .AllowCredentials();
                });
            });

            return services;
        }

        /// <summary>
        /// 添加健康检查
        /// </summary>
        public static IServiceCollection AddCustomHealthChecks(this IServiceCollection services, IConfiguration configuration)
        {
            var healthChecksBuilder = services.AddHealthChecks();
         
            // 数据库健康检查
            var connectionString = configuration.GetConnectionString("DefaultConnection");
            if (!string.IsNullOrEmpty(connectionString))
            {
                healthChecksBuilder.AddNpgSql(connectionString, name: "postgresql", tags: new[] { "db", "postgresql" });
            }

            // Redis健康检查（如果配置了Redis）
            var redisConnectionString = configuration.GetConnectionString("Redis");
            if (!string.IsNullOrEmpty(redisConnectionString))
            {
                healthChecksBuilder.AddRedis(redisConnectionString, name: "redis", tags: new[] { "cache", "redis" });
            }

            // 文件系统健康检查
            var uploadPath = configuration["FileUpload:UploadPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "uploads");
            healthChecksBuilder.AddCheck("file_system", () =>
            {
                try
                {
                    Directory.CreateDirectory(uploadPath);
                    var testFile = Path.Combine(uploadPath, ".health_check");
                    File.WriteAllText(testFile, "health check");
                    File.Delete(testFile);
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("File system is accessible");
                }
                catch (Exception ex)
                {
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Unhealthy("File system is not accessible", ex);
                }
            }, tags: new[] { "filesystem" });

            return services;
        }

        /// <summary>
        /// 使用健康检查端点
        /// </summary>
        public static IApplicationBuilder UseCustomHealthChecks(this IApplicationBuilder app)
        {
            app.UseHealthChecks("/health", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
            {
                ResponseWriter = async (context, report) =>
                {
                    context.Response.ContentType = "application/json";
                    var result = System.Text.Json.JsonSerializer.Serialize(new
                    {
                        status = report.Status.ToString(),
                        checks = report.Entries.Select(e => new
                        {
                            name = e.Key,
                            status = e.Value.Status.ToString(),
                            description = e.Value.Description,
                            duration = e.Value.Duration,
                            tags = e.Value.Tags
                        }),
                        totalDuration = report.TotalDuration
                    }, new System.Text.Json.JsonSerializerOptions
                    {
                        PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
                        WriteIndented = true
                    });
                    
                    await context.Response.WriteAsync(result);
                }
            });

            // 简化的健康检查端点
            app.UseHealthChecks("/health/ready", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
            {
                Predicate = check => check.Tags.Contains("ready")
            });

            app.UseHealthChecks("/health/live", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
            {
                Predicate = _ => false
            });

            return app;
        }

        /// <summary>
        /// 配置静态文件服务
        /// </summary>
        public static IApplicationBuilder UseCustomStaticFiles(this IApplicationBuilder app, IConfiguration configuration)
        {
            var uploadPath = configuration["FileUpload:UploadPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "uploads");
            
            // 配置上传文件的静态文件服务
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(uploadPath),
                RequestPath = "/uploads",
                ServeUnknownFileTypes = false,
                OnPrepareResponse = ctx =>
                {
                    // 设置缓存策略
                    var headers = ctx.Context.Response.GetTypedHeaders();
                    headers.CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
                    {
                        Public = true,
                        MaxAge = TimeSpan.FromDays(30)
                    };
                    
                    // 添加安全头
                    ctx.Context.Response.Headers["X-Content-Type-Options"] = "nosniff";
                }
            });

            return app;
        }

        /// <summary>
        /// 启动时的中间件清理任务
        /// </summary>
        public static IApplicationBuilder UseMiddlewareCleanupTasks(this IApplicationBuilder app, IConfiguration configuration)
        {
            // 注册清理任务
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
            
            // 应用程序启动时的任务
            lifetime.ApplicationStarted.Register(() =>
            {
                _ = Task.Run(async () =>
                {
                    while (!lifetime.ApplicationStopping.IsCancellationRequested)
                    {
                        try
                        {
                            // 清理过期的速率限制记录（每小时清理一次）
                            RateLimitingMiddleware.CleanupExpiredClients(TimeSpan.FromHours(24));
                            
                            // 清理过期的临时上传文件
                            var uploadPath = configuration["FileUpload:UploadPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "uploads");
                            var tempPath = Path.Combine(uploadPath, "temp");
                            if (Directory.Exists(tempPath))
                            {
                                var cutoff = DateTime.UtcNow.AddHours(-24);
                                var expiredDirs = Directory.GetDirectories(tempPath)
                                    .Where(dir => Directory.GetCreationTimeUtc(dir) < cutoff)
                                    .ToList();
                                
                                foreach (var dir in expiredDirs)
                                {
                                    try
                                    {
                                        Directory.Delete(dir, true);
                                    }
                                    catch { } // 忽略删除失败的情况
                                }
                            }
                            
                            await Task.Delay(TimeSpan.FromHours(1), lifetime.ApplicationStopping);
                        }
                        catch (OperationCanceledException)
                        {
                            break;
                        }
                        catch (Exception)
                        {
                            // 忽略清理任务中的异常
                        }
                    }
                });
            });

            return app;
        }
    }
}
